package com.facebook_graph;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

//import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Base64;
import org.json.simple.parser.JSONParser;

public class FbDecoderUtil {
	
	public static int MAX_AGE = 3600;
	public static String EXPRIES = "expires";
	public static String OAUTH_TOKEN = "oauth_token";
	public static String USER_ID = "user_id";
	public static String ALGORITHM = "algorithm";
	public static String ISSUED_AT = "issued_at";
	public static String ACCESS_TOKEN = "access_token";
	public static String EXPIRES_IN = "expires_in";
	public static String LOGIN_USER = "user";

	public static byte[] base64_url_decode(String input) {
		return new Base64(true).decode(input);
		// return null;
	}

	public static Map parse_signed_request(String input, String secret)
			throws Exception {
		return parse_signed_request(input, secret, MAX_AGE);
	}

	public static Map parse_signed_request(String input, String secret,
			int max_age) throws Exception {
		String[] split = input.split("[.]", 2);

		String encoded_sig = split[0];
		String encoded_envelope = split[1];
		JSONParser parser = new JSONParser();
		String base64Code = new String(base64_url_decode(encoded_envelope));
		Map envelope = (Map) parser.parse(base64Code);
		String algorithm = (String) envelope.get(ALGORITHM);

		if (!algorithm.equals("AES-256-CBC HMAC-SHA256")
				&& !algorithm.equals("HMAC-SHA256")) {
			throw new Exception("Invalid request. (Unsupported algorithm.)");
		}

		if (((Long) envelope.get(ISSUED_AT)) < System.currentTimeMillis()
				/ 1000 - max_age) {
			throw new Exception("Invalid request. (Too old.)");
		}

		byte[] key = secret.getBytes();
		SecretKey hmacKey = new SecretKeySpec(key, "HMACSHA256");
		Mac mac = Mac.getInstance("HMACSHA256");
		mac.init(hmacKey);
		byte[] digest = mac.doFinal(encoded_envelope.getBytes());

		if (!Arrays.equals(base64_url_decode(encoded_sig), digest)) {
			throw new Exception("Invalid request. (Invalid signature.)");
		}

		// for requests that are signed, but not encrypted, we"re done
		if (algorithm.equals("HMAC-SHA256")) {
			return envelope;
		}

		// otherwise, decrypt the payload
		byte[] iv = base64_url_decode((String) envelope.get("iv"));
		IvParameterSpec ips = new IvParameterSpec(iv);

		SecretKey aesKey = new SecretKeySpec(key, "AES");
		Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
		cipher.init(Cipher.DECRYPT_MODE, aesKey, ips);

		byte[] raw_ciphertext = base64_url_decode((String) envelope
				.get("payload"));
		byte[] plaintext = cipher.doFinal(raw_ciphertext);
		return (Map) parser.parse(new String(plaintext).trim());
	}

	/**
	 * 获得AccessToken
	 * 
	 * @param paramsMap
	 */
	public static String getAccessToken(java.util.Map paramsMap) {
		if (paramsMap == null) {
			return null;
		}
		return (String) paramsMap.get(FbDecoderUtil.OAUTH_TOKEN);
	}

	/**
	 * 获得USER_ID
	 * 
	 * @param paramsMap
	 */
	public static String getUserId(java.util.Map paramsMap) {
		if (paramsMap == null) {
			return null;
		}
		return (String) paramsMap.get(FbDecoderUtil.USER_ID);
	}

	/**
	 * 获得Expires
	 * 
	 * @param paramsMap
	 */
	public static String getExpires_in(java.util.Map paramsMap) {
		if (paramsMap == null) {
			return null;
		}
		return (String) paramsMap.get(FbDecoderUtil.EXPIRES_IN);
	}

	/**
	 * 获得Expires
	 * 
	 * @param paramsMap
	 */
	public static Object getLoginUser(java.util.Map paramsMap) {
		if (paramsMap == null) {
			return null;
		}
		return paramsMap.get(FbDecoderUtil.LOGIN_USER);
	}

	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String input = in.readLine();
		String secret = "0a99183fd7a3b970a753fc60f8feacac";
		// String secret = "6fed25fc55ea159aebbefcc12af96501";
		// String secret = "13750c9911fec5865d01f3bd00bdf4db";
		System.out.println(parse_signed_request(input, secret));
		System.out.println(parse_signed_request(input, secret).get(
				FbDecoderUtil.LOGIN_USER));
	}

}
